#!/usr/bin/perl
#---------------------#
#  PROGRAM:  wt.pl    #
#---------------------#

use strict;
use warnings;
use wt;
use Getopt::Long;
use Pod::Usage;
use FindBin '$Bin';
use Data::Dumper;

use Log::Log4perl qw(:easy);
use YAML qw(LoadFile);

our $VERSION = '0.102080';

my @args = @ARGV;
my $debug = 0; 

my $c = 0;
my $wtp = "$Bin/..";

&ptlnd("Bin : ".$Bin);
&ptlnd("wtp : ".$wtp);

load_cfg();
#&ptlnd(Dumper( $c ));

$debug = $$c{debug};
Log::Log4perl::init_and_watch($wtp.'/log4perl.conf',10);
my $logger = Log::Log4perl->get_logger('wt.log');

my $help        = 0;
my $doc         = 0;
my $open        = 0;   
my $see         = 0;   
my $enva        = 0;   
my $do7z        = 0;   
my $explorer    = 0;   
my $uniq        = 0;   
my $minus       = 0;   
my $smtp        = 0;   
my $ssh         = 0;   
my $proc        = 0;   

my $test        = 0;   

my $mysqlserver = 0;   
my $h2server    = 0;   

my $rsnserver   = 0;   
my $caserver    = 0;   
my $jtserver    = 0;   

my $mvn   = 0;
my $cmvn  = 0;
my $imvn  = 0;
my $rmvn  = 0;
my $tmvn  = 0;

my $catcreate = 0;   
my $cmcreate  = 0;   
my $cvcreate  = 0;   
my $cccreate  = 0;   


#TODO_ITEM 
#
#  add 7z param for 7z some prj
#
#  prj list: hello wt
#  
#  use cmd : 7z a hello.7z hello-7z/

GetOptions(
    'help|?'            => \$help,
    'doc'               => \$doc,
    'open'              => \$open,
    'see'               => \$see ,
    'enva'              => \$enva,
    '7z'                => \$do7z,
    'explorer'          => \$explorer,
    'uniq'              => \$uniq,
    'minus'             => \$minus,
    'smtp'              => \$smtp,
    'ssh'               => \$ssh,
    'proc'              => \$proc,

    'test'              => \$test,

    'mvn'               => \$mvn ,            
    'cmvn'              => \$cmvn,
    'rmvn'              => \$rmvn,
    'imvn'              => \$imvn,
    'tmvn'              => \$tmvn,

    'mysqlserver'       => \$mysqlserver ,    
    'h2server'          => \$h2server,

    'jtserver'          => \$jtserver ,       
    'caserver'          => \$caserver ,       
    'rsnserver'         => \$rsnserver,       

    'catcreate'         => \$catcreate,
    'cvcreate'          => \$cmcreate,
    'cccreate'          => \$cmcreate,
    'cmcreate'          => \$cmcreate

);

&printArgs() if($debug); 

vim ()                        if ( !&hasArgs(0) );

## <- Misc -> ##
pod2usage (0)                 if ( $help );        
poddoc    ( )                 if ( $doc  );        
&vimopen  ( $0 )              if ( $open );        
&see      ( $0 )              if ( $see  );        
&enva     ( $args[1] )        if ( $enva );
&do7z     ()                  if ( $do7z   );        
&explorer ()                  if ( $explorer );
&uniq     ()                  if ( $uniq );         
&minus    ()                  if ( $minus );         
&smtp     ()                  if ( $smtp );         
&ssh      ()                  if ( $ssh  );         
&proc     ()                  if ( $proc );         

&test     ()                  if ( $test );         

## <- db-server -> ##
&mysql_server()              if ( $mysqlserver);    
&h2_server()                 if ( $h2server);    

## <- Web-Server -> ##
&resin_server()              if ( $rsnserver);    

## <- mvn-related -> ##
&mvn ()                      if ( $mvn);         
&mvn_start_jetty ()          if ( $rmvn);         
&mvn_create()                if ( $cmvn);         
&mvn_install()               if ( $imvn);         
&mvn_test_single()           if ( $tmvn);         

## <- cat-related -> ##
catalyst_server()            if ( $caserver);     
&catalyst_create()            if ( $catcreate);     

vim ( $args[0] )             if (  &hasArgs(0) );     

sub load_cfg {
    if (-e "$Bin/my_conf"){
        $c= LoadFile( "$Bin/my_conf" );
    }
    elsif(-e "$Bin/conf"){
        $c= LoadFile( "$Bin/conf" );
    }
    else {
        die("conf files not found.");
    }
}

sub poddoc {
    use Pod::Perldoc ();
    Pod::Perldoc->run();
    &exitwt();
}

sub vim {

    $ENV{'WTPATH'} = $wtp;
    $ENV{'MYSYS'} = $$c{mysys};
    $ENV{'RV_VIMRT'} = "$wtp/$$c{vim}{rtpath}";

    my ( $file_name ) = @_;
    my $cmd = "$$c{vim}{home}/$$c{vim}{bin} -S $wtp/$$c{vim}{rc} -n ";
    $cmd.="\"$file_name\"" if (defined $file_name);

    sysexec( $cmd );

    &exitwt();
}

sub vimopen {

    my $file;

    use Switch;
    switch( $args[1] ) {

        case [ "conf", "cfg"  ]   { $file = qq|/pl/conf|;      }
        case [ "rvrc", "rc"   ]   { $file = qq|/vim/rvrc.vim|; }
        case [ "vimrc", "vrc" ]   { $file = qq|/vim/vimrc|;    }

        else { $file = qq|/pl/rv.pl|; }
    }

    vim ( $wtp.$file ) if ( defined $file );
    
    &exitwt();
}

sub see {
    use Switch;

    if($args[1]) {
        my $seefile = $$c{see}{$args[1]};
        if($seefile){
            if( -e $seefile ){
                my $see_cmd = "tail -f";
                $see_cmd = $args[2] if($args[2]);

                my $cmd = "$see_cmd $seefile";

                $logger->debug("see_cmd:  $cmd");
                system $cmd;
            }
            else{
                $logger->error("seefile [$seefile] not found");
            }
        }
        else{
            $logger->error("no key [$args[1]] configed");
        }
    }
    else{
        $logger->error("no param seefile");
    }

    &exitwt();
}


sub enva() {
    my ( $s ) = @_;
    print eval $s if(defined $s);
    &exitwt();
}

sub do7z() {

    my $file;
    use Switch;
    switch( $args[1] ) {
        case [ "conf", "cfg"  ]   { $file = qq|/pl/conf|;      }
        case [ "rvrc", "rc"   ]   { $file = qq|/vim/rvrc.vim|; }
        case [ "vimrc", "vrc" ]   { $file = qq|/vim/vimrc|;    }
        else { $file = qq|/wt|; }
    }

    my $cmd = "7z a $wtp/..$file.7z $wtp";
    ptlnd($cmd);

    system $cmd;

    &exitwt();
}

sub explorer {
    my $opendir = ".";
    $opendir = $args[1] if ( $args[1] ) ;
    my $cmd = qq/$$c{file_explorer} $opendir/;

    system $cmd;
    &exitwt();
}

sub msys {
    my $opendir = ".";
    $opendir = $args[1] if ( $args[1] ) ;
    my $cmd = qq/$$c{file_explorer} $opendir/;

    $cmd = q|g:\msys\1.0\bin\rxvt.exe  -backspacekey  -sl 2500 -fg Green -bg Black -sr -fn Courier-12 -geometry 80x30 -e /bin/sh --login -i|;

    ptlnd $cmd;

    system $cmd;
    &exitwt();
}

#TODO 
sub catalyst_create() {
    push @INC,$$c{catalyst}{extlib};

    my $cmd= "perl  $$c{catalyst}{catalyst} ";
    $cmd = $cmd.$args[1] if($args[1]) ;
    print $cmd;

    sysexec($cmd);

    &exitwt();
}

#sub mvn_init () { $ENV{'PATH'} = $mvn{home}.q{/bin;}.$ENV{'PATH'}; set_java_home(); }

sub mvn_create () {
    if ( &hasArgs(1) && &hasArgs(2)) {
        my $mvn_home = $$c{maven}{home}; 
        my $mvn_bin  = $$c{maven}{bin};
        my $m        = $mvn_home.$mvn_bin;

        my $mvn_app  = $$c{maven}{cmd}{c}{app};
        my $mvn_atf  = $$c{maven}{cmd}{c}{artifact};
        my $mvn_c    = $$c{maven}{cmd}{c}{$args[1]};
        $mvn_c       = $mvn_app." ".$mvn_c if $mvn_app ne $mvn_c;

        my $cmd = $m." ".$mvn_c." ".$mvn_atf."$args[2]";
        ptlnd($cmd);
        
        exec $cmd;

    } else { print q# Error: Please give type and name to create a mvn prj ! like "rv -cmvn app hello"#; }

    die(q{out!});
}

sub mvn_install() {
    $ENV{'JAVA_HOME'} = $$c{java}{home};

    if ( $#args==4 ) {
        my $cmd = qq{/bin/mvn install:install-file -DgroupId=$args[1] -DartifactId=$args[2] -Dversion=$args[3] -Dpackaging=jar -Dfile=$args[4]};
        ptlnd($cmd);
         
        exec $$c{maven}{home}.$cmd;
    }
    elsif( $#args==1 && $args[1] eq "prj") {
        my $cmd = $$c{maven}{home}.$$c{maven}{bin}." clean install -o";
        $cmd .=" -Dmaven.test.skip=true" if("true" eq $$c{maven}{notest});
        ptlnd($cmd);

        exec $cmd;
    } else { print q# Error: The cmd must like this : 'rv -imvn groupId artifactId version file'#; }


    die(q{out!});
}

sub mvn_test_single() {
    $ENV{'JAVA_HOME'} = $$c{java}{home};

    my $cmd=$$c{maven}{home}.$$c{maven}{bin}." test -e -Dtest=";
    ptln $#args;
    if($#args==0) {
        $cmd.= $$c{maven}{test};
    }
    else {
        $cmd.= $args[1];
    }
    ptlnd($cmd);

    exec $cmd;

    die(q{out!});
}

sub mvn () {
    $ENV{'JAVA_HOME'} = $$c{java}{home};

    my $args= "";
    shift @args;
    foreach (@args) {
        $args.=" ".$_;
    }
    
    my $cmd = $$c{maven}{home}."/bin/mvn".$args;
    $cmd .=" -o" if("true" eq $$c{maven}{offline});
    $cmd .=" -Dmaven.test.skip=true" if("true" eq $$c{maven}{notest});
    ptlnd($cmd); 

    exec $cmd; 

    die(q{out!});
}

sub resin_server() {
    if ( $args[1] && $args[1] eq "o" ) {
        exec "explorer $$c{resin}{home}\\webapps";
        die(q{out!});
    }

    set_java_home();
    my $cmd = "$$c{resin}{home}/httpd.exe";
    ptlnd($cmd);

    system $cmd;

    die(q{out!});
}

sub mvn_start_jetty () {
    $ENV{'JAVA_HOME'} = $$c{java}{home};

    my $cmd = $$c{maven}{home}."/bin/mvn jetty:run-war -e ";
    $cmd .=" -o" if("true" eq $$c{maven}{offline});
    ptlnd($cmd);

    exec $cmd;

    die(q{out!});
}

sub mysql_server () {
    my $cmd = "$$c{mysql}{home}$$c{mysql}{bin}";
    system $cmd;
    die(q{out!});
}

sub h2_server() {
    my $cmd = "java -cp ";
    my @jars = ();

    opendir DH, "$$c{h2}{home}/bin" or die "Cannot open $$c{h2}{home}/bin : $!";
    foreach my $file (readdir DH) {
        push (@jars,"$$c{h2}{home}/bin/".$file) 
        if not -d $file 
            and $file =~/.*\.jar/;
    }
    $cmd .= join(';',@jars)." org.h2.tools.Console";

    system $cmd;
    die(q{out!});
}

sub uniq() {
    if ($#args < 2) {
        ptln "Usage: wt -uniq file1 file2\n";
        exitwt();
    }

    ptlnd("args[0] $args[0]");
    ptlnd("args[1] $args[1]");
    ptlnd("args[2] $args[2]");

    open(FH,"$args[1]") or die "Couldn't open [ $args[1] ] for reading: $!";
    open(FO,">$args[2]") or die "Couldn't open [ $args[2] ] for reading: $!";

    my %e=();
    while(<FH>) {
        if (not exists $e{$_}) {
            print FO $_;
            $e{$_}=0;
        }
    }
    close(FH); 
    close(FO);

    exitwt();
}

sub minus() {

    use DBI;

    my $db_file="data.db";
    my $dbh = DBI->connect("dbi:SQLite:dbname=$db_file","","");

    $dbh->do("CREATE TABLE users(
        username varchar(255),
        password varchar(100),
        born date,
        test1 date,
        test2 varchar(500),
        test3 varchar(500),
        urlt varchar(500))");
    $dbh->do("CREATE INDEX idx_name_users ON users(username)");

    my $sth = $dbh->prepare(q{INSERT INTO users VALUES (?,?,?,?,?,?,?)});

    foreach my $i (1,2,3,4){
        $sth->bind_param(1,"ssss$i");
        $sth->bind_param(2,"passwd");
        $sth->bind_param(3,20090102);
        $sth->bind_param(4,20090102);
        $sth->bind_param(5,"none");
        $sth->bind_param(6,"none");
        $sth->bind_param(7,"http://www.supersun.biz");
        $sth->execute or die $dbh->errstr;
    }

    my $ary_ref=$dbh->selectall_arrayref(q{SELECT * FROM users});
    foreach my $entry (@$ary_ref){
        print "@$entry\n";
    }

    $dbh->disconnect;

    exitwt();
}

sub smtp() {

    my ($host, $user, $pass, $from, $tolist, $subject, $msg);

    $host       = $$c{smtp}{host};
    $user       = $$c{smtp}{user};
    $pass       = $$c{smtp}{pass};
    $from       = $$c{smtp}{from};
    $tolist     = $$c{smtp}{tolist};
    $subject    = $$c{smtp}{subject};
    $msg        = $$c{smtp}{content};

    foreach( @$host ) {
        my $l_host = $_;
        foreach( @$from ) {
            &sendmail($l_host,$user, $pass, $from, $tolist, $subject, $msg );
        }
    }

    exitwt();
}

sub ssh() {

    my $user = "";
    my $pass = "";
    my $host = "";

    if( $#args==1 ) {
        $host = $$c{ssh}{$args[1]}{host};
        $user = $$c{ssh}{$args[1]}{user};
        $pass = $$c{ssh}{$args[1]}{pass};
    }
    else {
        die qq/This option work with two parm!/;
    }

    my $sshexp = "$wtp/ssh.exp";

    if(! -e $sshexp){
        ptfile($sshexp, &sshscript);
        chmod 0777,$sshexp;
    }

    sysexec("$sshexp $host $user $pass");

    exitwt();
}

sub proc() {

    my $grep = $$c{proc}{$args[1]}{grep};
    my $key = $$c{proc}{$args[1]}{key};
    my $proc_name = $args[1];

    my $start_cmd = "$$c{proc}{$proc_name}{startcmd}";
    my $stop_cmd = "$$c{proc}{$proc_name}{stopcmd}";

    my $pid = get_pid($grep, $key);

    if( $pid > 0 ) {
        ptln "\nproc [$proc_name] ( pid $pid ) is running";
    }
    else {
        ptln "\nproc [$proc_name] is not running";
    }

    use Switch;
    switch( $args[2] ) {
        case [ "stop",      "0" ]   { 
            if($pid > 0){
                &sysexec($stop_cmd); 
                &wait_proc($proc_name, 1);
            }
        }
        case [ "kill", "k" ]   { 
            if($pid > 0) {
                &sysexec("kill -9 ".$pid); 
            }
            else {
                ptln "no [$proc_name] process found!";
            }
        }
        case [ "restart",   "2" ]   { 
            if($pid > 0) {
                &sysexec($stop_cmd);
                &wait_proc($proc_name, 1);
            }
            &sysexec($start_cmd);
            &wait_proc($proc_name);
        }
        case [ "forcerestart",   "4" ]   { 
            if($pid > 0) {
                &sysexec("kill -9 ".$pid); 
                &wait_proc($proc_name, 1);
            }
            &sysexec($start_cmd);
            &wait_proc($proc_name);
        }
        case [ "st"] {} # do nothing 
        else { # start proc
            if($pid < 0){
                &sysexec($start_cmd);
                &wait_proc($proc_name);
            }
        };
    }

    exitwt();
}

sub wait_proc(){

    my ( $proc_name, $stop ) = @_;

    my $grep = $$c{proc}{$proc_name}{grep};
    my $key = $$c{proc}{$proc_name}{key};
    my $timeout = $$c{proc}{timeout};
    $timeout = 30 if ! $timeout;

    my $pid = get_pid($grep, $key);
    my $msg = "starting proc $proc_name";
    $logger->debug("grep: $grep  key: $key  pid: $pid ");

    my $nums = 0;
    if($stop){
        $msg = "stoping proc $proc_name( $pid ) ";
        ptln $msg;
        while($pid > 0){
            print '.'; sleep(1);
            $pid = get_pid($grep, $key);
            $nums++;
            last if $nums > $timeout;
        } print "\n";
    }else{
        ptln $msg;
        while($pid < 0){
            print '.'; sleep(1);
            $pid = get_pid($grep, $key);
            $nums++;
            last if $nums > $timeout;
        } print "\n";
    }
}

sub sshscript(){
    my $sshscript = 
'#!/usr/bin/expect -f
set timeout 30

set server [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]

spawn ssh $user@$server

expect {
  "> " { }
  "$ " { }
  "assword: " { 
        send "$pass\n" 
  }
  "(yes/no)? " { 
        send "yes\n"
  }
  default {
        send_user "Login failed\n"
        exit
  }
}

interact';
}


#### utils funcs 

#FIXME 
sub test() {
    
    $logger->debug('this is a debug message');
    $logger->info('this is an info message');
    $logger->warn('etc');
    $logger->error('..');
    $logger->fatal('..');
    
    exitwt()
}

sub printArgs() {
    return if(!$debug);

    my $info = qq*
    #----------------------------------# 
    # running file: $0
    #
    #   |
    #---|/
    *;

    print $info;

    my $num=0;
    foreach (@args) {
        $num++;
        &ptlnd( "\tArgs$num : ".$_) if(defined $_);
    }
    &ptlnd ($#args);
    #print  "has args" if(&hasArgs(0));
}

sub getFStor() { 
    return $$c{mysys} eq qq/win32/?';':':';
};

sub hasArgs() { $args[$_[0]]?1:0; }

sub is_root() { return $ENV{'USER'} eq "root"; }

sub set_java_home() { $ENV{'JAVA_HOME'} = $$c{java}{home} };

sub ptlnd() { 
    my $debug_info = shift;
    if($debug){
        &ptln($debug_info);
#        if( not -e $$c{debug_log}) {
#            my $cmd = "echo 'init debug_log file' >> $$c{debug_log}";
#            sysexec($cmd);                                                                                        
#        }
#
#        open (MYFILE, ">>$$c{debug_log}");
#        print MYFILE "debug: ".$debug_info."\n";
#        close (MYFILE);
    }
}

sub ptfile(){
    my ($file,$content) = @_;
    open (MYFILE, ">>$file");
    print MYFILE $content;
    close (MYFILE);
}

sub exitwt() {
    my $info = qq/ wt exit /; 

    $info="\n" if(!$debug);
    die( $info ); 
}

sub sysexec() {
    my ( $s ) = @_;

    if($debug) {
        &ptln("exec ".$s);
    }

    if( $$c{mysys} eq qq/win32/ ) { exec $s; }
    else { system $s; }
}

sub getTime {
    my $time = shift || time();
    my ($sec,$min,$hour,$mday,$mon,$year,$day,$yday,$isdst) = localtime($time);

    $year += 1900;
    $mon ++;

    $min  = '0'.$min  if length($min)  < 2;
    $sec  = '0'.$sec  if length($sec)  < 2;
    $mon  = '0'.$mon  if length($mon)  < 2;
    $mday = '0'.$mday if length($mday) < 2;
    $hour = '0'.$hour if length($hour) < 2;

    my $weekday = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$day];

    return { 'second' => $sec,
        'minute' => $min,
        'hour'   => $hour,
        'day'    => $mday,
        'month'  => $mon,
        'year'   => $year,
        'weekNo' => $day,
        'wday'   => $weekday,
        'yday'   => $yday
    };
}

sub sendmail() {

    my ($host,$user, $pass, $from, $to_addr, $subject, $msg ) = @_;
    my $mdate = "mdate";

    use Net::SMTP;
    my $smtp = Net::SMTP->new( $host );
    if(!defined($smtp) || !($smtp)) {
        print "SMTP ERROR: Unable to open smtp session.\n";
        exitwt();
    }
    if (! ($smtp->auth( $user, $pass ) ) ) {
        &ptln ("auth error");
        exitwt();
    }
    if (! ($smtp->mail( $from ) ) ) {
        exitwt();
    }
    if (! ($smtp->recipient( ( ref($to_addr) ? @$to_addr : $to_addr ) ) ) ) {
        exitwt();
    }

    exitwt();

#    $smtp->data( $msg );
    $smtp->data();
    $smtp->datasend("To:  $to_addr\n");
    $smtp->datasend("From:  $from\n");
    $smtp->datasend("Date: $mdate\n");
    $smtp->datasend("Subject: $subject\n");
    $smtp->datasend("MIME-Version: 1.0\n");
    $smtp->datasend("Content-type: text/html\n");
    $smtp->datasend("Content-Transfer-Encoding: 7bit\n");
    $smtp->datasend("\n");
    $smtp->datasend("$msg\n\n");
    $smtp->dataend();

    $smtp->quit;
}


=head1 NAME

wt.pl - Daily Tool

=head1 SYNOPSIS

wt [options]

 Options: -{ help | open | see | enva | do7z | explorer | uniq | [cirt]mvn | runserver }

    if no option, vim will be invoke to edit a file.

    -help|?           display this help
    -open             Open sys file
                      args2->file mapping table:
                      [ default        ]   { /pl/rv.pl     }
                      [ "conf" , "cfg" ]   { /pl/conf      }
                      [ "rvrc" , "rc"  ]   { /vim/rvrc.vim }
                      [ "vimrc", "vrc" ]   { /vim/vimrc    }
    -see 
    -enva
    -do7z
    -explorer
    -uniq             replace duplicate line in file
    -smtp             send mail
    -ssh              ssh to a server
    -proc             proc start stop mgr by conf

    -mysqlserver      Start mysql server
    -h2server         Start H2 server

    -rsnserver        Start resin server
    -caserver         Start My Catalyst Server
    -tomcat           Start tomcat server

    -mvn option       Exec mvn command
    -cmvn             Create mvn project
    -imvn             Install jar to respo
    -rmvn             Start jetty server(mvn plugin)
    -tmvn option      Exec mvn test [ default all | give one Test Class ]

 Examples:
     $wt file.txt
     $wt -tomcat
     $wt -tomcat s (shutdown tomcat)

 See also:
    Nothing Here!

=head1 DESCRIPTION

Invoke some other util command or program via this wt interface

Some detail description

=head1 AUTHOR

Rentie <rwtest@gmail.com>
Maintained by myself.

=head1 COPYRIGHT

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
